package fag.core.game;

import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;

import fag.core.collision.Hitbox;
import fag.core.collision.Quadtree;
import fag.core.geometry.Rectangle2D;

/**
 * Classe d'une scène du jeu.
 * @author lumz.
 */
public class Scene {
	
	private Rectangle2D bounds = new Rectangle2D();
	
	private List<Camera> cameras = new ArrayList<Camera>();
	
	private Quadtree quadtree = null;
	
	private List<Doodad> doodads = new ArrayList<Doodad>();
	
	/**
	 * Constructeur par défault.
	 */
	public Scene(Rectangle2D bounds) {
		this.bounds = bounds;
		quadtree = new Quadtree(bounds);
	}
	
	/**
	 * Ajouter une caméra à la scène.
	 * @param camera La caméra à ajouter.
	 */
	public void addCamera(Camera camera) {

		if(!cameras.contains(camera))
			cameras.add(camera);
		
		camera.scene = this;
	}
	
	/**
	 * Ajouter une Doodad à la scène.
	 * @param doodad Le Doodad à ajouter.
	 */
	public void addDoodad(Doodad doodad) {
		
		if(!doodads.contains(doodad)) {
			doodads.add(doodad);
		}
		
		doodad.scene = this;
	}
	
	/**
	 * Obtenir la boîte englobante de la scène.
	 * @return La boîte englobante de la scène.
	 */
	public Rectangle2D getBounds() {
		return bounds.clone();
	}
	
	/**
	 * Obtenir la liste des doodads de la scène.
	 * @return La liste des doodads de la scène.
	 */
	public List<Doodad> getDoodads() {
		return new ArrayList<Doodad>(doodads);
	}
	
	/**
	 * Retirer une caméra à la scène.
	 * @param camera La caméra à retirer.
	 */
	public void removeCamera(Camera camera) {
		
		if(cameras.remove(camera))
			camera.scene = null;
	}
	
	/**
	 * Retirer un Doodad à la scène.
	 * @param doodad Le Doodad à retirer.
	 */
	public void removeDoodad(Doodad doodad) {
		
		if(doodads.remove(doodad)) {
			doodad.scene = null;
			addDirtyRegion(doodad.getBounds());
		}
	}
	
	/**
	 * Ajoute une zone de la scène qui est à redessiner.
	 * @param region La zone de la scène qui est à redessiner.
	 */
	void addDirtyRegion(Rectangle2D region) {
		
		for(Camera camera : cameras)
			camera.addDirtyRegion(region);
	}
	
	/**
	 * Dessine la scène.
	 * @param graphics2d
	 */
	void draw(Graphics2D graphics2d) {
		for(Doodad doodad : doodads)
			doodad.draw(graphics2d);
	}
	
	/**
	 * Avancer la scène dans le temps.
	 * @param dt L'avancement.
	 */
	void step(double dt) {
		
		forwardAnimations(dt);
		
		rebuildQuadtree();
	}
	
	/**
	 * Avancer les animations de la scène.
	 * @param dt La durée de l'avancement.
	 */
	private void forwardAnimations(double dt) {
		
		for(Doodad doodad : doodads) {
			doodad.forward(dt);
		}
	}
	
	/**
	 * Reconstruire l'arbre quaternaire de la scène.
	 */
	private void rebuildQuadtree() {
		
		List<Hitbox> hitboxes = new ArrayList<Hitbox>();
		
		for(Doodad doodad : doodads)
			hitboxes.add(doodad.getHitbox());
			
		quadtree.build(hitboxes);
	}
}
